package nl.utwente.eemcs.common.helpers;


import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import nl.utwente.eemcs.graph.Node;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;

public class XMLParser {
	private GraphBuilder graphBuilder;
	private String filename;
	private Document doc;

	public XMLParser(String filename) {
		this.filename = filename;
	}

	public GraphBuilder parse() {
		try {
			graphBuilder = new GraphBuilder();

			// Open document and parse
			DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
			doc = dBuilder.parse(filename);
			doc.getDocumentElement().normalize();
			
			// Parse document
			parseNodes();
			parseControlEdges();
			parseDataItems();
			parseDataEdges();
			parseDistributions();
			parseRestrictions();

			return graphBuilder;
		} catch (Exception ex) {
			ex.printStackTrace();
			return null;
		}
	}
	
	private void parseNodes() throws Exception {
		NodeList nodes = doc.getElementsByTagName("node");
		for (int i=0; i<nodes.getLength(); i++) {
			org.w3c.dom.Node node = nodes.item(i);
			String id = getAttributeValue(node, "id");
			String name = getAttributeValue(node, "name");
			String type = getAttributeValue(node, "type");
			
			Node n = graphBuilder.addNode(id, name, type);
			
			/*if (node.getAttributes().getNamedItem("loopNode") != null)
				n = graphBuilder.addLoopBranchNode(id, name, type);
				else
				n = graphBuilder.addNode(id, name, type);*/
			
			/*if (node.getAttributes().getNamedItem("loopNode") != null)
				n.addAttribute("loopNode", getAttributeValue(node, "loopNode"));*/
			if (node.getAttributes().getNamedItem("branchNode") != null)
				n.addAttribute("branchNode", getAttributeValue(node, "branchNode"));			
			if (node.getAttributes().getNamedItem("evaluateBefore") != null)
				n.addAttribute("evaluateBefore", Boolean.parseBoolean(getAttributeValue(node, "evaluateBefore")));			
		}
	}
	
	private void parseControlEdges() throws Exception {
		NodeList controlEdges = doc.getElementsByTagName("controlEdge");
		for (int i=0; i<controlEdges.getLength(); i++) {
			org.w3c.dom.Node node = controlEdges.item(i);
			String from = getAttributeValue(node, "from");
			String to = getAttributeValue(node, "to");
			String label = getAttributeValue(node, "label");
			
			// Create control edge
			graphBuilder.addControlEdge(from, to, label);
		}	
	}
	
	private void parseDataItems() throws Exception {
		NodeList dataItems = doc.getElementsByTagName("dataItem");
		for (int i=0; i<dataItems.getLength(); i++) {
			org.w3c.dom.Node node = dataItems.item(i);
			String name = getAttributeValue(node, "name");
			
			// Create data item
			graphBuilder.addDataItem(name);
		}
	}
	
	private void parseDataEdges() throws Exception {
		NodeList dataEdges = doc.getElementsByTagName("dataEdge");
		for (int i=0; i<dataEdges.getLength(); i++) {
			org.w3c.dom.Node node = dataEdges.item(i);
			String nodeName = getAttributeValue(node, "node");
			String dataItem = getAttributeValue(node, "dataItem");
			String type = getAttributeValue(node, "type");
			
			// Create data edge
			graphBuilder.addDataEdge(nodeName, dataItem, type);
		}
	}
	
	private void parseDistributions() throws Exception {
		NodeList distributions = doc.getElementsByTagName("distribution");
		for (int i=0; i<distributions.getLength(); i++) {
			org.w3c.dom.Node node = distributions.item(i);
			String nodeName = getAttributeValue(node, "node");
			String location = getAttributeValue(node, "location");
			
			// Add distribution location
			graphBuilder.addActivityDistribution(nodeName, location);
		}
	}
	
	private void parseRestrictions() throws Exception {
		NodeList restrictions = doc.getElementsByTagName("restriction");
		for (int i=0; i<restrictions.getLength(); i++) {
			org.w3c.dom.Node node = restrictions.item(i);
			String dataItem = getAttributeValue(node, "dataItem");
			String location = getAttributeValue(node, "location");
			
			// Add data distribution
			graphBuilder.addDataDistributionRestriction(dataItem, location);
		}		
	}
	
	private String getAttributeValue(org.w3c.dom.Node node, String attribute) {
		return node.getAttributes().getNamedItem(attribute).getNodeValue();
	}
}
